/*
 * $URL: http://dnsprobe.googlecode.com/svn/trunk/dnsprobe/src/dnsprobe/gui/ViewMain.java $
 * 
 * Copyright (c) 2009, Anonymous
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Anonymous nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY ANONYMOUS ''AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL ANONYMOUS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

package dnsprobe.gui;

import static dnsprobe.Constants.COMMAND_CHANGE_CUSTOM_NAMESERVER;
import static dnsprobe.Constants.COMMAND_CHANGE_NAMESERVER;
import static dnsprobe.Constants.COMMAND_LOAD_HOSTLIST;
import static dnsprobe.Constants.COMMAND_SAVE_EXPORT;
import static dnsprobe.Constants.COMMAND_START_RESOLVE;
import static dnsprobe.Constants.COMMAND_STOP_RESOLVE;
import static dnsprobe.Constants.EMPTY_STRING;
import static dnsprobe.Constants.GUI_LINE_SEPARATOR;
import static dnsprobe.Constants.GUI_MAIN_BUTTON_BROWSE;
import static dnsprobe.Constants.GUI_MAIN_BUTTON_EXPORT;
import static dnsprobe.Constants.GUI_MAIN_BUTTON_START;
import static dnsprobe.Constants.GUI_MAIN_BUTTON_STOP;
import static dnsprobe.Constants.GUI_MAIN_LABEL_BROWSE;
import static dnsprobe.Constants.GUI_MAIN_LABEL_EXPORT;
import static dnsprobe.Constants.GUI_MAIN_LABEL_EXPORT_CHOICE_ALL;
import static dnsprobe.Constants.GUI_MAIN_LABEL_EXPORT_CHOICE_DIFF;
import static dnsprobe.Constants.GUI_MAIN_LABEL_EXPORT_CHOICE_EQUAL;
import static dnsprobe.Constants.GUI_MAIN_LABEL_PROGRESS_COMPARE;
import static dnsprobe.Constants.GUI_MAIN_LABEL_PROGRESS_RESOLVE;
import static dnsprobe.Constants.GUI_MAIN_LOG_FONT;
import static dnsprobe.Constants.GUI_MAIN_TITLE;
import static dnsprobe.Constants.RESOURCE_BANNER;
import static dnsprobe.Constants.RESOURCE_ICON;

import java.awt.Toolkit;
import java.io.File;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

import dnsprobe.Application;
import dnsprobe.controller.Controller;
import dnsprobe.data.AccessProvider;
import dnsprobe.data.Statistics;
import dnsprobe.gui.model.AccessProviderModel;
import dnsprobe.gui.model.IpTableModel;
import dnsprobe.gui.renderer.IpTableCellRenderer;
import dnsprobe.io.FileHandler;


/**
 * Das GUI
 * 
 * @author BerndBernhardson
 * @author anon004
 * @author snoop
 * @version $Id: ViewMain.java 164 2009-07-08 01:42:55Z bernhardson@gmx.net $
 *
 */
public class ViewMain extends JFrame implements View.Main
{
	private static final long  serialVersionUID = 1L;

	private final FileChooser  fileChooser;
	
	private final JPanel       mainPanel;
	private final JLabel       bannerLabel;

	private final JButton      loadHostlistButton;
	private final JTextField   pathTextField;
	
	private final JButton      fireButton;
	private final JComboBox    accessProviderChooser;
	private final JTextField   accessProviderTextField;
	
	private final JScrollPane  ipTablePane;
	private final JTable       ipTable;
	
	private final JLabel       resolveLabel;
	private final JProgressBar resolveProgressBar;
	private final JLabel       compareLabel;
	private final JProgressBar compareProrgessBar;
	
	private final JScrollPane  textAreaPane;
	private final JTextArea    textArea;
	
	private final JLabel       exportLabel;
	private final JComboBox    exportTypeChooser;
	private final JButton      exportButton;
	private final JButton      stopButton;
	
	/**
	 * Konstruktor
	 */
	public ViewMain(final Controller.Main controller)
	{
		super();
		
		setLayout(null);
		setBounds(100, 20, 640, 700);
		setResizable(false);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSystemLookAndFeel();
		setTitle(GUI_MAIN_TITLE);
		setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource(RESOURCE_ICON)));
		
		mainPanel = new JPanel();
		mainPanel.setLayout(null);	
		mainPanel.setBounds(0, 0, 640, 700);
		
		fileChooser = new FileChooser();
		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		
		//----------------------------------------------------------------------
		// zeile: banner
		//----------------------------------------------------------------------
		
		bannerLabel = new JLabel(new ImageIcon(getClass().getResource(RESOURCE_BANNER)));
		bannerLabel.setBounds(20, 10, 600, 118);
		
		
		//----------------------------------------------------------------------
		// zeile: datei import
		//----------------------------------------------------------------------
		
		loadHostlistButton = new JButton(GUI_MAIN_BUTTON_BROWSE); 
		loadHostlistButton.setBounds(20, 140, 130, 25);
		loadHostlistButton.setActionCommand(COMMAND_LOAD_HOSTLIST);
		loadHostlistButton.addActionListener(controller);
		
		pathTextField = new JTextField(GUI_MAIN_LABEL_BROWSE);
		pathTextField.setBounds(170, 140, 450, 25);
		pathTextField.setEditable(false);

		
		//----------------------------------------------------------------------
		// zeile: starten + nameserver-auswahl
		//----------------------------------------------------------------------
		
		fireButton = new JButton(GUI_MAIN_BUTTON_START);
		fireButton.setBounds(20, 170, 130, 25);
		fireButton.setActionCommand(COMMAND_START_RESOLVE);
		fireButton.addActionListener(controller);
		
		accessProviderChooser = new JComboBox(new AccessProviderModel());
		accessProviderChooser.setBounds(170, 170, 215, 25);
		accessProviderChooser.setActionCommand(COMMAND_CHANGE_NAMESERVER);
		accessProviderChooser.addActionListener(controller);
		
		final AccessProvider selectedAccessProvider;
		
		selectedAccessProvider = (AccessProvider)accessProviderChooser.getSelectedItem();
		
		accessProviderTextField = new JTextField();
		accessProviderTextField.setBounds(405, 170, 215, 25);
		accessProviderTextField.setText(selectedAccessProvider.getAddress());
		accessProviderTextField.setEditable(selectedAccessProvider.isEditable());
		accessProviderTextField.setActionCommand(COMMAND_CHANGE_CUSTOM_NAMESERVER);
		accessProviderTextField.addActionListener(controller);


		//----------------------------------------------------------------------
		// zeile: ergebnis-daten
		//----------------------------------------------------------------------
		
		ipTable = new JTable(new IpTableModel());
		ipTable.setDefaultRenderer(String.class, new IpTableCellRenderer());
		
		ipTablePane = new JScrollPane();
		ipTablePane.setBounds(20, 200, 600, 250);
		ipTablePane.setSize(600, 250);
		ipTablePane.setViewportView(ipTable);
		
		
		//----------------------------------------------------------------------
		// zeilen: status-balken
		//----------------------------------------------------------------------
		
		resolveLabel = new JLabel(GUI_MAIN_LABEL_PROGRESS_RESOLVE);
		resolveLabel.setBounds(20, 460, 120, 25);
		
		resolveProgressBar = new JProgressBar(0, 100);
		resolveProgressBar.setBounds(150, 460, 470, 25);
		
		compareLabel = new JLabel(GUI_MAIN_LABEL_PROGRESS_COMPARE);
		compareLabel.setBounds(20, 490, 140, 25);
		
		compareProrgessBar = new JProgressBar(0, 100);
		compareProrgessBar.setBounds(150, 490, 470, 25);
		
		//----------------------------------------------------------------------
		// zeile: logfile
		//----------------------------------------------------------------------
		
		textArea = new JTextArea();
		textArea.setEditable(false);
		textArea.setFont(GUI_MAIN_LOG_FONT);
		
		textAreaPane = new JScrollPane();
		textAreaPane.setBounds(20, 525, 600, 110);
		textAreaPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		textAreaPane.setViewportView(textArea);
		
		
		//----------------------------------------------------------------------
		// zeile: export + stop
		//----------------------------------------------------------------------

		exportLabel = new JLabel(GUI_MAIN_LABEL_EXPORT);
		exportLabel.setBounds(20, 640, 190, 25);
		exportLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
		
		exportTypeChooser = new JComboBox();
		exportTypeChooser.setBounds(200, 640, 150, 25);
		exportTypeChooser.addItem(GUI_MAIN_LABEL_EXPORT_CHOICE_ALL);
		exportTypeChooser.addItem(GUI_MAIN_LABEL_EXPORT_CHOICE_DIFF);
		exportTypeChooser.addItem(GUI_MAIN_LABEL_EXPORT_CHOICE_EQUAL);
		
		exportButton = new JButton(GUI_MAIN_BUTTON_EXPORT);
		exportButton.setBounds(355, 640, 130, 25);
		exportButton.setActionCommand(COMMAND_SAVE_EXPORT);
		exportButton.addActionListener(controller);

		stopButton = new JButton(GUI_MAIN_BUTTON_STOP);
		stopButton.setBounds(490, 640, 130, 25);
		stopButton.setActionCommand(COMMAND_STOP_RESOLVE);
		stopButton.addActionListener(controller);
		

		//----------------------------------------------------------------------
		// JFrame bauen
		//----------------------------------------------------------------------
		
		mainPanel.add(bannerLabel);
		mainPanel.add(loadHostlistButton);
		mainPanel.add(pathTextField);
		mainPanel.add(fireButton);
		mainPanel.add(accessProviderChooser);
		mainPanel.add(accessProviderTextField);
		mainPanel.add(ipTablePane);
		mainPanel.add(resolveLabel);
		mainPanel.add(resolveProgressBar);
		mainPanel.add(compareLabel);
		mainPanel.add(compareProrgessBar);
		mainPanel.add(textAreaPane);
		mainPanel.add(exportLabel);
		mainPanel.add(exportTypeChooser);
		mainPanel.add(exportButton);
		mainPanel.add(stopButton);
		
		// setvisible erst zum schluss true setzen um lag am anfang zu vermeiden
		add(mainPanel);
		setVisible(true);
	}
	
	private void setSystemLookAndFeel()
	{
		try
		{
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch(final Exception e)
		{
		}
	}

	/**
	 * Offnet den Dateiauswahl-Dialog zum Laden einer Datei
	 * 
	 * @return Ein File-Objekt wenn eine datei ausgewaehlt wurde, null bei abbruch oder fehler
	 */
	public File chooseInputFile()
	{
		if(fileChooser.showOpenDialog(loadHostlistButton) != JFileChooser.APPROVE_OPTION)
		{
			return null;
		}
		
		final File file;
		
		file = fileChooser.getSelectedFile();
		
		return file;
	}
	
	/**
	 * Offnet den Dateiauswahl-Dialog zum Speichern einer Datei
	 * 
	 * @param preSelection Der Dateiname der vorausgewaehlt werden soll
	 * 
	 * @return Ein File-Objekt wenn eine datei ausgewaehlt wurde, null bei abbruch oder fehler
	 */
	public File chooseOutputFile(final File preSelection)
	{
		fileChooser.setSelectedFile(preSelection);
		
		if(fileChooser.showSaveDialog(exportButton) != JFileChooser.APPROVE_OPTION)
		{
			return null;
		}
		
		final File file;
		
		file = fileChooser.getSelectedFile();
		
		return file;
	}
	
	
	/**
	 * Liefert den aktuellen Text des Nameserverfeldes
	 * 
	 * @return Der aktuelle Text des Nameserverfeldes
	 */
	public String getAccessProviderAddess()
	{
		return accessProviderTextField.getText();
	}
	
	/**
	 * Aktualisiert das Nameserverfeld
	 * 
	 * @param accessProvider der neue AccessProvider
	 */
	public void setAccessProviderAddress(final AccessProvider accessProvider)
	{
		accessProviderTextField.setText(accessProvider.getAddress());
		accessProviderTextField.setEditable(accessProvider.isEditable());
	}
	
	/**
	 * Liefert das AccessProvider-Objekt des momentan ausgewaehlten Nameservers
	 * 
	 * @return Das AccessProvider-Objekt
	 */
	public AccessProvider getSelectedAccessProvider()
	{
		if(accessProviderChooser.getSelectedItem() == null)
		{
			return null;
		}
		
		return (AccessProvider)accessProviderChooser.getSelectedItem();
	}
	
	/**
	 * Liefert den momentan ausgewaehlten Export-Filter
	 * 
	 * @return Den momentan ausgewaehlten Export-Filter
	 * 
	 * @see FileHandler#EXPORT_ALL
	 * @see FileHandler#EXPORT_DIFF
	 * @see FileHandler#EXPORT_EQUAL
	 */
	public int getSelectedExportType()
	{
		final String currentExportType;
		
		int result;
		
		currentExportType = (String)exportTypeChooser.getSelectedItem();
		
		result = FileHandler.EXPORT_DEFAULT;
		
		if(currentExportType.equals(GUI_MAIN_LABEL_EXPORT_CHOICE_ALL)) 
		{
			result = FileHandler.EXPORT_ALL;
		}
		if(currentExportType.equals(GUI_MAIN_LABEL_EXPORT_CHOICE_EQUAL))
		{
			result = FileHandler.EXPORT_EQUAL;
		}
		if(currentExportType.equals(GUI_MAIN_LABEL_EXPORT_CHOICE_DIFF))
		{
			result = FileHandler.EXPORT_DIFF;
		}
		
		return result;
	}
	

	
	

	/**
	 * Aktualisiert den Pfad der ausgewaehlten Datei
	 * 
	 * @param path der neue Pfad
	 */
	public void updateImportPath(final String path)
	{
		pathTextField.setText(path);
	}

	/**
	 * Aktualisiert die Statistiken
	 */
	public void updateStatistics()
	{
		final Statistics statistics;
		
		statistics = Application.getData().getStatistics();
		
		resolveProgressBar.setValue(statistics.getResolveProgressPercentInt());
		//checkStatusDNS.setString(Float.toString(statistics.getResolveProgressPercentFloat()) + "%");
		
		compareProrgessBar.setValue(statistics.getCompareProgressPercentInt());
		//checkStatusCompare.setString(Float.toString(statistics.getCompareProgressPercentFloat()) + "%");
	}
	
	/**
	 * Aktualisiert die IpTable
	 */
	public void updateIpTableModel()
	{
		final IpTableModel model;
		
		model = (IpTableModel)ipTable.getModel();
		
		model.fireTableDataChanged();
	}
	
	/**
	 * Schreibt eine Textzeile mit Zeilenumbruch ins Statusfeld
	 * 
	 * @param parts Die Teile der Textzeile
	 */
	public void printLog(final Object... parts)
	{
		final StringBuilder builder;
		
		builder = new StringBuilder();
		
		for(Object part: parts)
		{
			builder.append(part);
		}
		
		builder.append(GUI_LINE_SEPARATOR);
		
		textArea.append(builder.toString());
	}
	
	/**
	 * Leert das Statusfeld
	 */
	public void clearLog()
	{
		textArea.setText(EMPTY_STRING);
	}
}
